package auth

import config.JwtConfig
import play.api.http.HeaderNames
import play.api.mvc._
import utils.JwtUtils

import java.time.Clock
import javax.inject.{Inject, Singleton}
import scala.concurrent.{ExecutionContext, Future}
import scala.util.Failure
import implicits.Implicits._
import play.api.mvc.Results.NotFound
import shared.pojo.Pojo.UserInfo
import shared.pojo.Role

/**
 * Created by yz on 10/8/2022
 */

case class UserRequest[A](userInfo: UserInfo, request: Request[A]) extends WrappedRequest[A](request)

class AuthAction @Inject()(parser: BodyParsers.Default)(implicit ec: ExecutionContext, config: JwtConfig) extends
  ActionBuilder[UserRequest, AnyContent] {

  override def invokeBlock[A](request: Request[A], block: UserRequest[A] => Future[Result]): Future[Result] = {
    AuthTool.authenticate(request).flatMap { userInfo =>
      block(UserRequest(userInfo = userInfo, request = request))
    }
  }

  override def parser: BodyParser[AnyContent] = parser

  override protected def executionContext: ExecutionContext = ec

}
@Singleton
class AuthActionWrapper @Inject()(authAction: AuthAction)(implicit ec: ExecutionContext, config: JwtConfig) {

  def FilterAction(roles: List[Role])(implicit ec: ExecutionContext) = new ActionFilter[UserRequest] {

    override protected def executionContext: ExecutionContext = ec

    override protected def filter[A](request: UserRequest[A]): Future[Option[Result]] = {
      val resultOp = Role.withNameInsensitive(request.userInfo.role) match {
        case x if roles.contains(x) => None
        case _ => Some(
          Results.Forbidden(ujson.Obj("valid" -> false, "message" -> "当前用户没有访问权限！"))
        )
      }
      Future.successful(resultOp)
    }
  }

  def apply(role: Role): ActionBuilder[UserRequest, AnyContent] = {
    apply(List(role))
  }

  def apply(roles: List[Role]) = {
    authAction.andThen(FilterAction(roles))
  }

}
